#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
浏览器管理模块
使用Selenium控制浏览器进行自动化操作
"""

import os
import time
import logging
from typing import Optional, List, Dict, Any
from pathlib import Path

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.common.exceptions import TimeoutException, NoSuchElementException, WebDriverException
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.microsoft import EdgeChromiumDriverManager

class BrowserManager:
    """浏览器管理器"""
    
    def __init__(self, browser_config: Dict[str, Any]):
        self.config = browser_config
        self.driver: Optional[webdriver.Chrome] = None
        self.wait: Optional[WebDriverWait] = None
        self.logger = logging.getLogger(__name__)
        
    def start_browser(self, use_existing_profile: bool = True) -> bool:
        """启动浏览器
        
        Args:
            use_existing_profile: 是否使用现有的浏览器配置文件（保持登录状态）
            
        Returns:
            bool: 启动是否成功
        """
        try:
            # 尝试使用Chrome浏览器
            options = webdriver.ChromeOptions()
            
            # 基本配置
            if self.config.get('headless', False):
                options.add_argument('--headless')
                
            window_size = self.config.get('window_size', [1920, 1080])
            options.add_argument(f'--window-size={window_size[0]},{window_size[1]}')
            
            # 使用现有用户配置文件以保持登录状态
            if use_existing_profile:
                user_data_dir = os.path.expanduser("~\\AppData\\Local\\Google\\Chrome\\User Data")
                if os.path.exists(user_data_dir):
                    options.add_argument(f'--user-data-dir={user_data_dir}')
                    options.add_argument('--profile-directory=Default')
                    
            # 其他有用的选项
            options.add_argument('--no-sandbox')
            options.add_argument('--disable-dev-shm-usage')
            options.add_argument('--disable-blink-features=AutomationControlled')
            options.add_experimental_option("excludeSwitches", ["enable-automation"])
            options.add_experimental_option('useAutomationExtension', False)
            
            # 自定义User-Agent
            user_agent = self.config.get('user_agent', '')
            if user_agent:
                options.add_argument(f'--user-agent={user_agent}')
                
            # 尝试启动Chrome
            try:
                service = ChromeService(ChromeDriverManager().install())
                self.driver = webdriver.Chrome(service=service, options=options)
                self.logger.info("Chrome浏览器启动成功")
            except Exception as e:
                self.logger.warning(f"Chrome启动失败，尝试Edge: {e}")
                # 如果Chrome失败，尝试Edge
                edge_options = webdriver.EdgeOptions()
                
                if self.config.get('headless', False):
                    edge_options.add_argument('--headless')
                    
                edge_options.add_argument(f'--window-size={window_size[0]},{window_size[1]}')
                
                if use_existing_profile:
                    edge_user_data_dir = os.path.expanduser("~\\AppData\\Local\\Microsoft\\Edge\\User Data")
                    if os.path.exists(edge_user_data_dir):
                        edge_options.add_argument(f'--user-data-dir={edge_user_data_dir}')
                        edge_options.add_argument('--profile-directory=Default')
                        
                edge_options.add_argument('--no-sandbox')
                edge_options.add_argument('--disable-dev-shm-usage')
                
                if user_agent:
                    edge_options.add_argument(f'--user-agent={user_agent}')
                    
                edge_service = EdgeService(EdgeChromiumDriverManager().install())
                self.driver = webdriver.Edge(service=edge_service, options=edge_options)
                self.logger.info("Edge浏览器启动成功")
                
            # 设置超时和等待
            timeout = self.config.get('timeout', 30)
            implicit_wait = self.config.get('implicit_wait', 10)
            
            self.driver.set_page_load_timeout(timeout)
            self.driver.implicitly_wait(implicit_wait)
            self.wait = WebDriverWait(self.driver, timeout)
            
            # 执行反检测脚本
            self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
            
            return True
            
        except Exception as e:
            self.logger.error(f"启动浏览器失败: {e}")
            return False
            
    def navigate_to(self, url: str) -> bool:
        """导航到指定URL"""
        try:
            self.logger.info(f"导航到: {url}")
            self.driver.get(url)
            time.sleep(2)  # 等待页面加载
            return True
        except Exception as e:
            self.logger.error(f"导航失败: {e}")
            return False
            
    def login(self, site_config: Dict[str, Any]) -> bool:
        """执行登录操作"""
        if not site_config.get('login_required', False):
            return True
            
        try:
            login_url = site_config.get('login_url')
            if login_url and login_url != self.driver.current_url:
                self.navigate_to(login_url)
                
            # 检查是否已经登录
            if self._is_already_logged_in(site_config):
                self.logger.info("检测到已登录状态")
                return True
                
            # 查找用户名输入框
            username_selector = site_config.get('username_selector')
            password_selector = site_config.get('password_selector')
            submit_selector = site_config.get('submit_selector')
            
            if not all([username_selector, password_selector]):
                self.logger.warning("缺少登录选择器配置")
                return False
                
            # 等待登录表单加载
            username_element = self.wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, username_selector))
            )
            
            password_element = self.driver.find_element(By.CSS_SELECTOR, password_selector)
            
            # 检查输入框是否已有内容（浏览器自动填充）
            if username_element.get_attribute('value') and password_element.get_attribute('value'):
                self.logger.info("检测到浏览器自动填充的登录信息")
                
                # 点击提交按钮
                if submit_selector:
                    submit_element = self.driver.find_element(By.CSS_SELECTOR, submit_selector)
                    submit_element.click()
                else:
                    # 如果没有提交按钮选择器，尝试按回车
                    password_element.send_keys(Keys.RETURN)
                    
                # 等待登录完成
                wait_time = site_config.get('wait_after_login', 3)
                time.sleep(wait_time)
                
                return self._is_already_logged_in(site_config)
            else:
                self.logger.warning("未检测到自动填充的登录信息，需要手动配置用户名密码")
                return False
                
        except TimeoutException:
            self.logger.error("登录超时")
            return False
        except Exception as e:
            self.logger.error(f"登录失败: {e}")
            return False
            
    def _is_already_logged_in(self, site_config: Dict[str, Any]) -> bool:
        """检查是否已经登录"""
        try:
            # 可以通过多种方式检查登录状态
            # 1. 检查URL变化
            login_url = site_config.get('login_url', '')
            current_url = self.driver.current_url
            
            if login_url and login_url in current_url:
                return False  # 还在登录页面
                
            # 2. 检查特定元素（如用户菜单、退出按钮等）
            logout_selectors = ['.logout', '.sign-out', '[href*="logout"]', '[href*="signout"]']
            for selector in logout_selectors:
                try:
                    self.driver.find_element(By.CSS_SELECTOR, selector)
                    return True  # 找到退出按钮，说明已登录
                except NoSuchElementException:
                    continue
                    
            # 3. 检查用户相关元素
            user_selectors = ['.user-name', '.username', '.profile', '.avatar']
            for selector in user_selectors:
                try:
                    self.driver.find_element(By.CSS_SELECTOR, selector)
                    return True  # 找到用户相关元素
                except NoSuchElementException:
                    continue
                    
            return False
            
        except Exception as e:
            self.logger.error(f"检查登录状态失败: {e}")
            return False
            
    def scroll_to_load_content(self, max_scrolls: int = 3) -> None:
        """滚动页面以加载更多内容"""
        try:
            for i in range(max_scrolls):
                # 滚动到页面底部
                self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
                time.sleep(2)  # 等待内容加载
                
                # 检查是否有新内容加载
                new_height = self.driver.execute_script("return document.body.scrollHeight")
                if i > 0 and new_height == getattr(self, '_last_height', 0):
                    break  # 没有新内容，停止滚动
                    
                self._last_height = new_height
                
        except Exception as e:
            self.logger.error(f"滚动加载内容失败: {e}")
            
    def get_page_source(self) -> str:
        """获取页面源码"""
        try:
            return self.driver.page_source
        except Exception as e:
            self.logger.error(f"获取页面源码失败: {e}")
            return ""
            
    def take_screenshot(self, filepath: str) -> bool:
        """截图"""
        try:
            self.driver.save_screenshot(filepath)
            return True
        except Exception as e:
            self.logger.error(f"截图失败: {e}")
            return False
            
    def close(self):
        """关闭浏览器"""
        try:
            if self.driver:
                self.driver.quit()
                self.driver = None
                self.wait = None
                self.logger.info("浏览器已关闭")
        except Exception as e:
            self.logger.error(f"关闭浏览器失败: {e}")
            
    def __enter__(self):
        """上下文管理器入口"""
        return self
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器退出"""
        self.close()